home *** CD-ROM | disk | FTP | other *** search
- static char rcsid[] = "$Author: cck $ $Date: 88/09/14 10:19:45 $";
- static char rcsident[] = "$Header: /src/local/mac/cap/etalk/RCS/kip_mpx.c,v 1.19 88/09/14 10:19:45 cck Rel $";
- static char revision[] = "$Revision: 1.19 $";
-
- /*
- * kip_mpx.c - talks to cap processes via udp
- *
- * demultiplexing communications point with various processes.
- * Two versions in here: one version speaks directly to KIP module
- * CAP clients (KIP). The other speaks on a modified range (MKIP)
- *
- * KIP writes atalk.local and cannot be used when the rebroadcaster
- * is in use. NOTE: THIS DOES NOT WORK CORRECTLY.
- * MKIP writes matalk.local (debugging mostly)
- *
- * This version really cheats and uses a different range of ports,
- * but the same encapsulation used for kip.
- *
- *
- * Copyright (c) 1988 by The Trustees of Columbia University
- * in the City of New York.
- *
- * Permission is granted to any individual or institution to use,
- * copy, or redistribute this software so long as it is not sold for
- * profit, provided that this notice and the original copyright
- * notices are retained. Columbia University nor the author make no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * Edit History:
- *
- * April 3, 1988 CCKim Created
- *
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/uio.h>
- #include <sys/time.h>
- #include <net/if.h>
- #include <netinet/in.h>
-
- #include <netat/appletalk.h>
- #include "mpxddp.h"
- #include "gw.h"
- #include "log.h"
-
- #define LOG_STD 2
-
- /*
- ethertalk to kip - try 1:
- o forward packets by sending to ddp udp port
- o receive packets by having the remote send to "bridge" socket
- o much like kip methods except different socket range and fewer
- conditions in lower level code
- */
-
- #ifndef MTAB
- # define MTAB "/etc/matalk.local"
- #endif
- #ifndef TAB
- # define TAB "/etc/atalk.local"
- #endif
-
- /* handle kip fakeout */
- #define mkip_rebPort 903
- #define kip_rebPort 902
-
- #define mddp2ipskt(s) (((s)&0x80) ? (s)+ddpNWKSUnix :(s)+200)
-
- struct kipdef {
- int s; /* socket */
- word net;
- byte node;
- byte bridge_node;
- struct sockaddr_in sin;
- };
-
- #define MKIP_HANDLE 0
- #define KIP_HANDLE 1
- #define NUM_KIP_HANDLE 2
-
- #define VALID_HANDLE(h) ((h) >= 0 && (h) < NUM_KIP_HANDLE)
- #define INVALID_HANDLE(h) ((h) >= NUM_KIP_HANDLE || (h) < 0)
- private struct kipdef kipdefs[NUM_KIP_HANDLE];
-
- #define KIP_PRIMARY 0 /* primary listening */
- #define KIP_SECONDARY 1 /* secondary: local to process */
-
- /* destination */
- private struct in_addr desthost;
-
- private DDP kddp;
- private LAP klap;
- private char kbuf[ddpMaxData+ddpSize]; /* add in space for lap */
-
- private int kip_init();
- private int mkip_init();
- private int kip_grab();
- private int kips_ahoy();
- private int kip_sendddp();
- private int kip_havenode();
- private int kip_havenet();
- private int kip_havezone();
-
- export struct mpxddp_module mkip_mpx = {
- "modified KIP forwarding",
- "MKIP",
- mkip_init,
- NULL, /* grab, don't do for now (ddpsrvc not done) */
- kip_sendddp,
- kip_havenode,
- kip_havenet,
- kip_havezone
- };
-
- export struct mpxddp_module kip_mpx = {
- "KIP forwarding",
- "KIP",
- #ifdef notdef
- /* doesn't work right because of the way kip routing is done, sigh */
- kip_init,
- NULL, /* grab, don't do for now (ddpsrvc not done) */
- kip_sendddp,
- kip_havenode,
- kip_havenet,
- kip_havezone
- #else
- NULL, /* init */
- NULL, /* grab, don't do for now (ddpsrvc not done) */
- NULL, /* senddp */
- NULL, /* havenode */
- NULL, /* have net */
- NULL /* have zone */
- #endif
- };
-
- private
- kip_listener(fd, k, level)
- int fd;
- struct kipdef *k;
- int level;
- {
- struct msghdr msg;
- struct iovec iov[3];
- int len;
- struct sockaddr_in from_sin;
-
- /* should check k */
- iov[0].iov_base = (caddr_t)&klap;
- iov[0].iov_len = lapSize;
- iov[1].iov_base = (caddr_t)&kddp;
- iov[1].iov_len = ddpSize;
- iov[2].iov_base = kbuf;
- iov[2].iov_len = ddpMaxData;
- msg.msg_name = (caddr_t) &from_sin;
- msg.msg_namelen = sizeof(from_sin);
- msg.msg_iov = iov;
- msg.msg_iovlen = 3;
- msg.msg_accrights = 0;
- msg.msg_accrightslen = 0;
- if ((len = recvmsg(fd,&msg,0)) < 0) {
- log(LOG_LOG|L_UERR, "recvmsg: kip listener");
- return(len);
- }
- /* could do rebroadcaster work here */
- if (len < (lapSize+ddpSize))
- return(-1);
- len -= (lapSize + ddpSize);
- if (klap.type != lapDDP)
- return(-1);
- switch (level) {
- case KIP_PRIMARY:
- if (klap.src != k->node) /* drop! must have wrong configuration */
- return(-1);
- if (kddp.srcNode != k->node || (kddp.srcNet != k->net && kddp.srcNet != 0))
- return(-1);
- break;
- case KIP_SECONDARY:
- /* always accept? */
- break;
- }
- ddp_output(NULL, &kddp, (byte *)kbuf, len);
- return(0);
- }
-
- /*
- * initialize kip forwarding
- *
- */
- private int
- mkip_init()
- {
- static int inited = FALSE;
- int i;
-
- if (inited)
- return(-1);
- if ((i = kips_ahoy(MKIP_HANDLE)) >= 0)
- inited = TRUE;
- return(i);
- }
-
- private int
- kip_init()
- {
- static int inited = FALSE;
- int i;
-
- if (inited)
- return(-1);
- if ((i = kips_ahoy(KIP_HANDLE)) >= 0)
- inited = TRUE;
- return(i);
- }
-
- private int
- kips_ahoy(h)
- {
- int cc;
- struct kipdef *k;
-
- if (h != MKIP_HANDLE && h != KIP_HANDLE)
- return(-1);
- k = &kipdefs[h];
- k->net = 0;
- k->node = 0;
- k->bridge_node = 0;
- desthost.s_addr = inet_addr("127.0.0.1");
- if (desthost.s_addr == -1)
- return(-1);
- /* no need to bind since we don't recv on this socket, just send... */
- if ((k->s = socket(AF_INET,SOCK_DGRAM,0)) < 0) {
- log(LOG_LOG|L_UERR, "socket: kip init");
- return(-1);
- }
- k->sin.sin_family = AF_INET;
- switch (h) {
- case MKIP_HANDLE:
- k->sin.sin_addr.s_addr = desthost.s_addr;
- k->sin.sin_port = htons(mkip_rebPort);
- break;
- case KIP_HANDLE:
- k->sin.sin_addr.s_addr = INADDR_ANY;
- k->sin.sin_port = htons(kip_rebPort);
- break;
- }
- if ((cc = bind(k->s, (caddr_t)&k->sin, sizeof(k->sin))) < 0) {
- close(k->s);
- log(LOG_LOG|L_UERR, "bind: kip init");
- return(cc);
- }
- fdlistener(k->s, kip_listener, k, KIP_PRIMARY);
- return(h);
- }
-
- private int
- kip_grab(hdl, skt)
- int hdl;
- int skt;
- {
- int fd, e;
- struct sockaddr_in lsin;
-
- if (INVALID_HANDLE(hdl))
- return(-1);
-
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- log(LOG_STD|L_UERR, "kip grab: socket for skt %d", skt);
- return(fd);
- }
- lsin.sin_family = AF_INET;
- /* bind only for localhost if mkip */
- switch (hdl) {
- case MKIP_HANDLE:
- lsin.sin_addr.s_addr = desthost.s_addr;
- lsin.sin_port = htons(ddp2ipskt(skt));
- break;
- case KIP_HANDLE:
- lsin.sin_addr.s_addr = INADDR_ANY;
- lsin.sin_port = (word)htons(mddp2ipskt(skt));
- break;
- }
- if (lsin.sin_port == 0) { /* same swapped or unswapped */
- close(fd); /* bad ddp socket */
- return(-1);
- }
- if ((e = bind(fd, (caddr_t)&lsin, sizeof(lsin))) < 0) {
- log(LOG_STD|L_UERR, "kip grab: bind for skt %d", skt);
- return(fd);
- }
- fdlistener(kipdefs[hdl].s, kip_listener, KIP_SECONDARY);
- return(fd);
- }
-
- /*
- * send along a ddp packet to the appropriate process
- *
- */
- private int
- kip_sendddp(hdl, ddp, data, cc)
- int hdl;
- DDP *ddp;
- caddr_t data;
- int cc;
- {
- struct msghdr msg;
- word destskt;
- int err;
- struct iovec iov[4];
- LAP lap;
- int t;
- struct kipdef *k;
-
- if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
- return(-1);
- k = &kipdefs[hdl];
-
- /* I THINK this is the right place for this -- this way, the demuxer */
- /* could possible handle multiple networks */
- if (ddp->dstNet != k->net && ddp->dstNode != k->node) /* drop */
- return(0);
-
- if (hdl == KIP_HANDLE)
- destskt = (word)htons(ddp2ipskt(ddp->dstSkt)+128);
- else
- destskt = (word)htons(mddp2ipskt(ddp->dstSkt));
- /* establish a dummy lap header */
- lap.type = lapDDP;
- lap.dst = k->node;
- lap.src = ddp->srcNode;
- iov[IOV_LAP_LVL].iov_base = (caddr_t) ⪅ /* LAP header */
- iov[IOV_LAP_LVL].iov_len = lapSize; /* size */
- iov[IOV_DDP_LVL].iov_base = (caddr_t) ddp;
- iov[IOV_DDP_LVL].iov_len = ddpSize;
- /* figure out what the data length should be */
- t = (ntohs(ddp->length)&ddpLengthMask) - ddpSize;
- /* if data size passed down is too large, then truncate. (sunos */
- /* trailing bytes or packet less than 60 bytes */
- /* so, pass back min of cc, length */
- iov[2].iov_len = (cc > t) ? t : cc;
- iov[2].iov_base = data;
- /* send through */
- k->sin.sin_addr = desthost;
- k->sin.sin_port = destskt;
- msg.msg_name = (caddr_t) &k->sin;
- msg.msg_namelen = sizeof(k->sin);
- msg.msg_iov = iov;
- msg.msg_iovlen = 3;
- msg.msg_accrights = 0;
- msg.msg_accrightslen = 0;
- if ((err = sendmsg(k->s,&msg,0)) < 0)
- log(LOG_LOG|L_UERR, "sendmsg: kip write");
- return(err);
- }
-
- /*
- * have node now -- just remember
- *
- */
- private int
- kip_havenode(hdl, node)
- int hdl;
- byte node;
- {
- if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
- return(FALSE);
- kipdefs[hdl].node = node;
- return(TRUE);
- }
-
- /*
- * have network now
- *
- */
- private int
- kip_havenet(hdl, net, node)
- word net;
- byte node;
- {
- if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
- return(FALSE);
- kipdefs[hdl].net = net;
- kipdefs[hdl].bridge_node = node;
- return(TRUE);
- }
-
- /*
- * have zone: ready to go
- *
- */
- private int
- kip_havezone(hdl, zone)
- int hdl;
- byte *zone;
- {
- FILE *fp;
- int i;
- struct kipdef *k;
- char *file;
-
- if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
- return(FALSE);
- k = &kipdefs[hdl];
- file = (hdl == MKIP_HANDLE) ? MTAB : TAB;
- if ((fp = fopen(file,"w")) == NULL) {
- log(LOG_LOG|L_UERR, "can't open %s", file);
- return(FALSE);
- }
- fprintf(fp, "%d.%d %d ",
- nkipnetnumber(k->net), nkipsubnetnumber(k->net),
- k->node);
- /* translate it for atalkdbm - ugh */
- for (i = *zone++; i ; i--, zone++) {
- switch (*zone) {
- case ' ':
- putc(' ', fp);
- break;
- case '_':
- putc('_', fp);
- putc('_', fp);
- break;
- default:
- putc(*zone, fp);
- }
- }
- putc('\n', fp);
- fprintf(fp, "%d.%d %d 127.0.0.1\n",
- nkipnetnumber(k->net), nkipsubnetnumber(k->net),
- k->bridge_node);
- fclose(fp);
- return(TRUE);
- }
-